#import "FilePickerPlugin.h"
#import "FileUtils.h"
#import "ImageUtils.h"

#import <AVFoundation/AVFoundation.h>
#import <MobileCoreServices/MobileCoreServices.h>
#import <Photos/Photos.h>
#import <PhotosUI/PHPhotoLibrary+PhotosUISupport.h>
#import <PhotosUI/PhotosUI.h>
#import <UIKit/UIKit.h>

#import "FLTImagePickerImageUtil.h"
#import "FLTImagePickerMetaDataUtil.h"
#import "FLTImagePickerPhotoAssetUtil.h"
#import "FLTPHPickerSaveImageToPathOperation.h"

///file_picker 8.0.6
//#ifdef PICKER_MEDIA
@import DKImagePickerController;

@interface FilePickerPlugin() <DKImageAssetExporterObserver>
//#else
//@interface FilePickerPlugin()
//#endif
@property (nonatomic) FlutterResult result;
@property (nonatomic) FlutterEventSink eventSink;
@property (nonatomic) UIImagePickerController *galleryPickerController;
@property (nonatomic) UIDocumentPickerViewController *documentPickerController;
@property (nonatomic) UIDocumentInteractionController *interactionController;
@property (nonatomic) MPMediaPickerController *audioPickerController;
@property (nonatomic) NSArray<NSString *> * allowedExtensions;
@property (nonatomic) BOOL loadDataToMemory;
@property (nonatomic) BOOL allowCompression;
@property (nonatomic) dispatch_group_t group;
@property (nonatomic) BOOL isSaveFile;

@property(assign, nonatomic) int maxImagesAllowed;

@property(copy, nonatomic) NSDictionary *arguments;

@property(strong, nonatomic) PHPickerViewController *pickerViewController API_AVAILABLE(ios(14));

@property (nonatomic, assign) PickerType type;

/// 是否可以选择视频
@property (nonatomic, assign) BOOL allowVideo;

@end

static const int SOURCE_CAMERA = 0;
static const int SOURCE_GALLERY = 1;

typedef NS_ENUM(NSInteger, ImagePickerClassType) { UIImagePickerClassType, PHPickerClassType };

@implementation FilePickerPlugin{
    UIImagePickerController *_imagePickerController;
  }

+ (void)registerWithRegistrar:(NSObject<FlutterPluginRegistrar>*)registrar {
    ///注册多通道
    FlutterMethodChannel* channel = [FlutterMethodChannel
                                     methodChannelWithName:@"miguelruivo.flutter.plugins.filepicker"
                                     binaryMessenger:[registrar messenger]];
    
    FlutterEventChannel* eventChannel = [FlutterEventChannel
                                         eventChannelWithName:@"miguelruivo.flutter.plugins.filepickerevent"
                                         binaryMessenger:[registrar messenger]];
    
    FilePickerPlugin* instance = [[FilePickerPlugin alloc] init];
    
    [registrar addMethodCallDelegate:instance channel:channel];
    [eventChannel setStreamHandler:instance];

    FlutterMethodChannel *imageChannel =
          [FlutterMethodChannel methodChannelWithName:@"plugins.flutter.io/image_picker"
                                      binaryMessenger:[registrar messenger]];
    FilePickerPlugin *imageInstance = [FilePickerPlugin new];
      [registrar addMethodCallDelegate:imageInstance channel:imageChannel];
}

- (UIImagePickerController *)getImagePickerController {
  return _imagePickerController;
}

- (UIImagePickerControllerCameraDevice)getCameraDeviceFromArguments:(NSDictionary *)arguments {
  NSInteger cameraDevice = [[arguments objectForKey:@"cameraDevice"] intValue];
  return (cameraDevice == 1) ? UIImagePickerControllerCameraDeviceFront
                             : UIImagePickerControllerCameraDeviceRear;
}

- (void)pickImageWithPHPicker:(int)maxImagesAllowed API_AVAILABLE(ios(14)) {
  PHPickerConfiguration *config =
      [[PHPickerConfiguration alloc] initWithPhotoLibrary:PHPhotoLibrary.sharedPhotoLibrary];
  config.selectionLimit = maxImagesAllowed;  // Setting to zero allow us to pick unlimited photos
    
    if (self.allowVideo==NO) {
        config.filter = [PHPickerFilter imagesFilter];
    }
    
  _pickerViewController = [[PHPickerViewController alloc] initWithConfiguration:config];
  _pickerViewController.delegate = self;
  _pickerViewController.presentationController.delegate = self;
  _pickerViewController.modalPresentationStyle = UIModalPresentationFullScreen;

  self.maxImagesAllowed = maxImagesAllowed;

  [self checkPhotoAuthorizationForAccessLevel];
}

- (void)pickImageWithUIImagePicker {
  _imagePickerController = [[UIImagePickerController alloc] init];
  _imagePickerController.modalPresentationStyle = UIModalPresentationFullScreen;
  _imagePickerController.delegate = self;
    
    if (self.allowVideo==NO) {
        _imagePickerController.mediaTypes = @[ (NSString *)kUTTypeImage ];
    }
    
  int imageSource = [[_arguments objectForKey:@"source"] intValue];

  self.maxImagesAllowed = 1;

  switch (imageSource) {
    case SOURCE_CAMERA:
          {if ([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera]) {
              // 设置相片选择控制器的来源
              _imagePickerController.sourceType = UIImagePickerControllerSourceTypeCamera;
          }
      [self checkCameraAuthorization];}
      break;
    case SOURCE_GALLERY:
          {if ([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypePhotoLibrary]) {
              // 设置相片选择控制器的来源
              _imagePickerController.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
          }
      [self checkPhotoAuthorization];}
      break;
    default:
      self.result([FlutterError errorWithCode:@"invalid_source"
                                      message:@"Invalid image source."
                                      details:nil]);
      break;
  }
}

- (instancetype)init {
    self = [super init];
    
    return self;
}

- (UIViewController *)viewControllerWithWindow:(UIWindow *)window {
    UIWindow *windowToUse = window;
    if (windowToUse == nil) {
        for (UIWindow *window in [UIApplication sharedApplication].windows) {
            if (window.isKeyWindow) {
                windowToUse = window;
                break;
            }
        }
    }
    
    UIViewController *topController = windowToUse.rootViewController;
    while (topController.presentedViewController) {
        topController = topController.presentedViewController;
    }
    return topController;
}

- (FlutterError *)onListenWithArguments:(id)arguments eventSink:(FlutterEventSink)events {
    _eventSink = events;
    return nil;
}

- (FlutterError *)onCancelWithArguments:(id)arguments {
    _eventSink = nil;
    return nil;
}

- (void)handleMethodCall:(FlutterMethodCall*)call result:(FlutterResult)result {
    if (_result) {
        result([FlutterError errorWithCode:@"multiple_request"
                                   message:@"Cancelled by a second request"
                                   details:nil]);
        _result = nil;
        return;
    }
    
    _result = result;
    
    if([call.method isEqualToString:@"clear"]) {
        _result([NSNumber numberWithBool: [FileUtils clearTemporaryFiles]]);
        _result = nil;
        return;
    }
    
    if([call.method isEqualToString:@"dir"]) {
        if (@available(iOS 13, *)) {
            [self resolvePickDocumentWithMultiPick:NO pickDirectory:YES];
        } else {
            _result([self getDocumentDirectory]);
            _result = nil;
        }
        return;
    }
    
    if ([@"customPickImage" isEqualToString:call.method]) {

        self.result = result;
        _arguments = call.arguments;
        int imageSource = [[_arguments objectForKey:@"source"] intValue];
        
        if ([_arguments.allKeys containsObject:@"allowVideo"]) {
            self.allowVideo = [[_arguments objectForKey:@"allowVideo"] boolValue];
        }

        if (imageSource == SOURCE_GALLERY) {  // Capture is not possible with PHPicker
          if (@available(iOS 14, *)) {
            // PHPicker is used
            [self pickImageWithPHPicker:1];
          } else {
            // UIImagePicker is used
            [self pickImageWithUIImagePicker];
          }
        } else {
          [self pickImageWithUIImagePicker];
        }
        self.type = IMAGEPICKER;
        
        return;
      }
    
    if ([@"customPickMultiImage" isEqualToString:call.method]) {
        self.type = IMAGEPICKER;
        
        _arguments = call.arguments;
        
        [_arguments setValue:@1 forKey:@"source"];
        
        if ([_arguments.allKeys containsObject:@"allowVideo"]) {
            self.allowVideo = [[_arguments objectForKey:@"allowVideo"] boolValue];
        }
        
    
      if (@available(iOS 14, *)) {
        self.result = result;
        [self pickImageWithPHPicker:0];
      } else {
          [self resolveMultiPickFromGallery:IMAGE withCompressionAllowed:self.allowCompression];
      }
        
        return;
    }
    
    NSDictionary * arguments = call.arguments;
    BOOL isMultiplePick = ((NSNumber*)[arguments valueForKey:@"allowMultipleSelection"]).boolValue;
    
    self.allowCompression = ((NSNumber*)[arguments valueForKey:@"allowCompression"]).boolValue;
    self.loadDataToMemory = ((NSNumber*)[arguments valueForKey:@"withData"]).boolValue;
    
    if([call.method isEqualToString:@"any"] || [call.method containsString:@"custom"]) {
        self.allowedExtensions = [FileUtils resolveType:call.method withAllowedExtensions: [arguments valueForKey:@"allowedExtensions"]];
        if(self.allowedExtensions == nil) {
            _result([FlutterError errorWithCode:@"Unsupported file extension"
                                        message:@"If you are providing extension filters make sure that you are only using FileType.custom and the extension are provided without the dot, (ie., jpg instead of .jpg). This could also have happened because you are using an unsupported file extension. If the problem persists, you may want to consider using FileType.any instead."
                                        details:nil]);
            _result = nil;
        } else if(self.allowedExtensions != nil) {
            [self resolvePickDocumentWithMultiPick:isMultiplePick pickDirectory:NO];
        }
        self.type = FILEPICKER;
    } else if([call.method isEqualToString:@"video"] || [call.method isEqualToString:@"image"] || [call.method isEqualToString:@"media"]) {
        [self resolvePickMedia:[FileUtils resolveMediaType:call.method] withMultiPick:isMultiplePick withCompressionAllowed:self.allowCompression];
        self.type = FILEPICKER;
    } else if([call.method isEqualToString:@"audio"]) {
        [self resolvePickAudioWithMultiPick: isMultiplePick];
        self.type = FILEPICKER;
    } else if([call.method isEqualToString:@"save"]) {
      NSString *fileName = [arguments valueForKey:@"fileName"];
	  NSString *fileType = [arguments valueForKey:@"fileType"];
      NSString *initialDirectory = [arguments valueForKey:@"initialDirectory"];
      FlutterStandardTypedData *bytes = [arguments valueForKey:@"bytes"];
      [self saveFileWithName:fileName fileType:fileType initialDirectory:initialDirectory bytes: bytes];
	} else  if ([@"pickImage" isEqualToString:call.method]) {

        self.result = result;
        _arguments = call.arguments;
        int imageSource = [[_arguments objectForKey:@"source"] intValue];

        if (imageSource == SOURCE_GALLERY) {  // Capture is not possible with PHPicker
          if (@available(iOS 14, *)) {
            // PHPicker is used
            [self pickImageWithPHPicker:1];
          } else {
            // UIImagePicker is used
            [self pickImageWithUIImagePicker];
          }
        } else {
          [self pickImageWithUIImagePicker];
        }
        self.type = IMAGEPICKER;
      } else if ([@"pickMultiImage" isEqualToString:call.method]) {
          
          _arguments = call.arguments;
          [_arguments setValue:@1 forKey:@"source"];
          
        if (@available(iOS 14, *)) {
          self.result = result;
          [self pickImageWithPHPicker:0];
        } else {
            [self resolveMultiPickFromGallery:IMAGE withCompressionAllowed:self.allowCompression];
        }
          self.type = IMAGEPICKER;
      } else if ([@"pickVideo" isEqualToString:call.method]) {
        _imagePickerController = [[UIImagePickerController alloc] init];
        _imagePickerController.modalPresentationStyle = UIModalPresentationFullScreen;
        _imagePickerController.delegate = self;
        _imagePickerController.mediaTypes = @[
          (NSString *)kUTTypeMovie, (NSString *)kUTTypeAVIMovie, (NSString *)kUTTypeVideo,
          (NSString *)kUTTypeMPEG4
        ];
        _imagePickerController.videoQuality = UIImagePickerControllerQualityTypeHigh;

        self.result = result;
        _arguments = call.arguments;

        int imageSource = [[_arguments objectForKey:@"source"] intValue];
        if ([[_arguments objectForKey:@"maxDuration"] isKindOfClass:[NSNumber class]]) {
          NSTimeInterval max = [[_arguments objectForKey:@"maxDuration"] doubleValue];
          _imagePickerController.videoMaximumDuration = max;
        }

        switch (imageSource) {
          case SOURCE_CAMERA:
            [self checkCameraAuthorization];
            break;
          case SOURCE_GALLERY:
            [self checkPhotoAuthorization];
            break;
          default:
            result([FlutterError errorWithCode:@"invalid_source"
                                       message:@"Invalid video source."
                                       details:nil]);
            break;
        }
          self.type = IMAGEPICKER;
      } else {
        result(FlutterMethodNotImplemented);
        _result = nil;
      }
}

- (NSString*)getDocumentDirectory {
    NSArray* paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    return paths.firstObject;
}

#pragma mark - Resolvers

- (void)saveFileWithName:(NSString*)fileName fileType:(NSString *)fileType initialDirectory:(NSString*)initialDirectory bytes:(FlutterStandardTypedData*)bytes{
    self.isSaveFile = YES;
    NSFileManager* fm = [NSFileManager defaultManager];
    NSURL* documentsDirectory = [fm URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask][0];
    NSURL* destinationPath = [documentsDirectory URLByAppendingPathComponent:fileName];
    NSError* error;
    if ([fm fileExistsAtPath:destinationPath.path]) {
        [fm removeItemAtURL:destinationPath error:&error];
        if (error != nil) {
            _result([FlutterError errorWithCode:@"Failed to remove file" message:[error debugDescription] details:nil]);
            error = nil;
        }
    }
    if(bytes != nil){
        [bytes.data writeToURL:destinationPath options:NSDataWritingAtomic error:&error];
        if (error != nil) {
            _result([FlutterError errorWithCode:@"Failed to write file" message:[error debugDescription] details:nil]);
            error = nil;
        }
    }
    self.documentPickerController = [[UIDocumentPickerViewController alloc] initWithURL:destinationPath inMode:UIDocumentPickerModeExportToService];
    self.documentPickerController.delegate = self;
    self.documentPickerController.presentationController.delegate = self;
    if(@available(iOS 13, *)){
       if(![[NSNull null] isEqual:initialDirectory] && ![@"" isEqualToString:initialDirectory]){
            self.documentPickerController.directoryURL = [NSURL URLWithString:initialDirectory];
        }
    }
    [[self viewControllerWithWindow:nil] presentViewController:self.documentPickerController animated:YES completion:nil];
}


- (void)resolvePickDocumentWithMultiPick:(BOOL)allowsMultipleSelection pickDirectory:(BOOL)isDirectory {
    self.isSaveFile = NO;
    @try{
        self.documentPickerController = [[UIDocumentPickerViewController alloc]
                                         initWithDocumentTypes: isDirectory ? @[@"public.folder"] : self.allowedExtensions
                                         inMode: isDirectory ? UIDocumentPickerModeOpen : UIDocumentPickerModeImport];
    } @catch (NSException * e) {
        Log(@"Couldn't launch documents file picker. Probably due to iOS version being below 11.0 and not having the iCloud entitlement. If so, just make sure to enable it for your app in Xcode. Exception was: %@", e);
        _result = nil;
        return;
    }
    
    if (@available(iOS 11.0, *)) {
        self.documentPickerController.allowsMultipleSelection = allowsMultipleSelection;
    } else if(allowsMultipleSelection) {
        Log(@"Multiple file selection is only supported on iOS 11 and above. Single selection will be used. Current iOS version: %@", [UIDevice currentDevice].systemVersion);
    }
    
    self.documentPickerController.modalPresentationStyle = UIModalPresentationFullScreen;
    
    self.documentPickerController.delegate = self;
    self.documentPickerController.presentationController.delegate = self;
    
    [[self viewControllerWithWindow:nil] presentViewController:self.documentPickerController animated:YES completion:nil];
}

- (void) resolvePickMedia:(MediaType)type withMultiPick:(BOOL)multiPick withCompressionAllowed:(BOOL)allowCompression  {
    
#ifdef PHPicker
    if (@available(iOS 14, *)) {
        PHPickerConfiguration *config = [[PHPickerConfiguration alloc] init];
        config.filter = type == IMAGE ? [PHPickerFilter imagesFilter] : type == VIDEO ? [PHPickerFilter videosFilter] : [PHPickerFilter anyFilterMatchingSubfilters:@[[PHPickerFilter videosFilter], [PHPickerFilter imagesFilter]]];
        config.preferredAssetRepresentationMode = self.allowCompression ? PHPickerConfigurationAssetRepresentationModeCompatible : PHPickerConfigurationAssetRepresentationModeCurrent;
        
        if(multiPick) {
            config.selectionLimit = 0;
        }
        
        PHPickerViewController *pickerViewController = [[PHPickerViewController alloc] initWithConfiguration:config];
        pickerViewController.delegate = self;
        pickerViewController.presentationController.delegate = self;
        pickerViewController.modalPresentationStyle = UIModalPresentationFullScreen;
        [[self viewControllerWithWindow:nil] presentViewController:pickerViewController animated:YES completion:nil];
        return;
    }
#endif
    
    if(multiPick) {
        [self resolveMultiPickFromGallery:type withCompressionAllowed:allowCompression];
        return;
    }
    
    NSArray<NSString*> * videoTypes = @[(NSString*)kUTTypeMovie, (NSString*)kUTTypeAVIMovie, (NSString*)kUTTypeVideo, (NSString*)kUTTypeMPEG4];
    NSArray<NSString*> * imageTypes = @[(NSString *)kUTTypeImage];
    
    self.galleryPickerController = [[UIImagePickerController alloc] init];
    self.galleryPickerController.delegate = self;
    self.galleryPickerController.presentationController.delegate = self;
    self.galleryPickerController.modalPresentationStyle = UIModalPresentationFullScreen;
    self.galleryPickerController.videoQuality = UIImagePickerControllerQualityTypeHigh;
    
    switch (type) {
        case IMAGE:
            self.galleryPickerController.mediaTypes = imageTypes;
            if (@available(iOS 11.0, *)) {
                self.galleryPickerController.imageExportPreset = allowCompression ? UIImagePickerControllerImageURLExportPresetCompatible : UIImagePickerControllerImageURLExportPresetCurrent;
            }
            break;
            
        case VIDEO:
            self.galleryPickerController.mediaTypes = videoTypes;
            if (@available(iOS 11.0, *)) {
                self.galleryPickerController.videoExportPreset = allowCompression ? AVAssetExportPresetHighestQuality : AVAssetExportPresetPassthrough;
            }
            break;
            
        default:
            self.galleryPickerController.mediaTypes = [videoTypes arrayByAddingObjectsFromArray:imageTypes];
            break;
    }
    
    [[self viewControllerWithWindow:nil] presentViewController:self.galleryPickerController animated:YES completion:nil];
    
    
}

- (void) resolveMultiPickFromGallery:(MediaType)type withCompressionAllowed:(BOOL)allowCompression {
    DKImagePickerController * dkImagePickerController = [[DKImagePickerController alloc] init];
    dkImagePickerController.modalPresentationStyle = UIModalPresentationFullScreen;
    
    UIAlertController* alert = [UIAlertController alertControllerWithTitle:@"" message:@"" preferredStyle:UIAlertControllerStyleAlert];
    UIActivityIndicatorView* indicator = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhite];
    
    UIViewController *currentViewController = [self viewControllerWithWindow:nil];
    if(_eventSink == nil) {
        // Create alert dialog for asset caching
        [alert.view setCenter: currentViewController.view.center];
        [alert.view addConstraint: [NSLayoutConstraint constraintWithItem:alert.view attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1 constant:100]];
        
        // Create a default loader if user don't provide a status handler
        indicator.hidesWhenStopped = YES;
        [indicator setCenter: alert.view.center];
        indicator.autoresizingMask = (UIViewAutoresizingFlexibleRightMargin | UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleBottomMargin | UIViewAutoresizingFlexibleTopMargin);
        [alert.view addSubview: indicator];
    }
    
    if (@available(iOS 11.0, *)) {
        DKImageAssetExporterConfiguration * exportConfiguration = [[DKImageAssetExporterConfiguration alloc] init];
        exportConfiguration.imageExportPreset = allowCompression ? DKImageExportPresentCompatible : DKImageExportPresentCurrent;
        exportConfiguration.videoExportPreset = allowCompression ? AVAssetExportPresetHighestQuality : AVAssetExportPresetPassthrough;
        dkImagePickerController.exporter = [dkImagePickerController.exporter initWithConfiguration:exportConfiguration];
    }
    
    dkImagePickerController.exportsWhenCompleted = YES;
    dkImagePickerController.showsCancelButton = YES;
    dkImagePickerController.sourceType = DKImagePickerControllerSourceTypePhoto;
    dkImagePickerController.assetType = type == VIDEO ? DKImagePickerControllerAssetTypeAllVideos : type == IMAGE ? DKImagePickerControllerAssetTypeAllPhotos : DKImagePickerControllerAssetTypeAllAssets;
    
    // Export status changed
    [dkImagePickerController setExportStatusChanged:^(enum DKImagePickerControllerExportStatus status) {
        
        if(status == DKImagePickerControllerExportStatusExporting && dkImagePickerController.selectedAssets.count > 0){
            Log("Exporting assets, this operation may take a while if remote (iCloud) assets are being cached.");
            
            if(self->_eventSink != nil){
                self->_eventSink([NSNumber numberWithBool:YES]);
            } else {
//                [indicator startAnimating];
//                [currentViewController showViewController:alert sender:nil];
            }
            
        } else {
            if(self->_eventSink != nil) {
                self->_eventSink([NSNumber numberWithBool:NO]);
            } else {
//                [indicator stopAnimating];
//                [alert dismissViewControllerAnimated:YES completion:nil];
            }
            
        }
    }];
    
    // Did cancel
    [dkImagePickerController setDidCancel:^(){
        self->_result(nil);
        self->_result = nil;
    }];
    
    // Did select
    [dkImagePickerController setDidSelectAssets:^(NSArray<DKAsset*> * __nonnull DKAssets) {
        NSMutableArray *urlPaths = [NSMutableArray array];
        for(DKAsset * asset in DKAssets) {
            if(asset.localTemporaryPath.absoluteURL != nil) {
                [urlPaths addObject:asset.localTemporaryPath.path];
            }
        }
        
        [self handleSavedPathList:urlPaths];
        return;
        
//        NSMutableArray<NSURL*>* paths = [[NSMutableArray<NSURL*> alloc] init];
//
//        for(DKAsset * asset in DKAssets) {
//            if(asset.localTemporaryPath.absoluteURL != nil) {
//                [paths addObject:asset.localTemporaryPath.absoluteURL];
//            }
//        }
//
//        [self handleResult: paths];
    }];
    
    [[self viewControllerWithWindow:nil] presentViewController:dkImagePickerController animated:YES completion:nil];
}

- (void) resolvePickAudioWithMultiPick:(BOOL)isMultiPick {
    
    
    self.audioPickerController = [[MPMediaPickerController alloc] initWithMediaTypes:MPMediaTypeAnyAudio];
    self.audioPickerController.delegate = self;
    self.audioPickerController.presentationController.delegate = self;
    self.audioPickerController.modalPresentationStyle = UIModalPresentationFullScreen;
    self.audioPickerController.showsCloudItems = YES;
    self.audioPickerController.allowsPickingMultipleItems = isMultiPick;
    
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 1 * NSEC_PER_SEC), dispatch_get_main_queue(), ^{
        if([self viewControllerWithWindow:nil].presentedViewController == nil){
            Log("Exporting assets, this operation may take a while if remote (iCloud) assets are being cached.");
        }
    });

    
    [[self viewControllerWithWindow:nil] presentViewController:self.audioPickerController animated:YES completion:nil];
}

- (void) handleResult:(id) files {
    _result([FileUtils resolveFileInfo: [files isKindOfClass: [NSArray class]] ? files : @[files] withData:self.loadDataToMemory]);
    _result = nil;
}

#pragma mark - Delegates

// DocumentPicker delegate - iOS 10 only
- (void)documentPicker:(UIDocumentPickerViewController *)controller didPickDocumentAtURL:(NSURL *)url{
    [self.documentPickerController dismissViewControllerAnimated:YES completion:nil];
    [self handleResult:url];
}

// DocumentPicker delegate
- (void)documentPicker:(UIDocumentPickerViewController *)controller
didPickDocumentsAtURLs:(NSArray<NSURL *> *)urls{
    
    if(_result == nil) {
        return;
    }
    if(self.isSaveFile){
        _result([urls objectAtIndex:0].path);
        _result = nil;
        return;
    }    
    [self.documentPickerController dismissViewControllerAnimated:YES completion:nil];
    
    if(controller.documentPickerMode == UIDocumentPickerModeOpen) {
        _result([urls objectAtIndex:0].path);
        _result = nil;
        return;
    }
	if(controller.documentPickerMode == UIDocumentPickerModeImport) {
        NSMutableArray<NSURL *> *newUrls = [NSMutableArray new];
        for (NSURL *url in urls) {
            // Create file URL to temporary folder
            NSURL *tempURL = [NSURL fileURLWithPath:NSTemporaryDirectory()];
            // Append filename (name+extension) to URL
            tempURL = [tempURL URLByAppendingPathComponent:url.lastPathComponent];
            NSError *error;
            // If file with same name exists remove it (replace file with new one)
            if ([[NSFileManager defaultManager] fileExistsAtPath:tempURL.path]) {
                [[NSFileManager defaultManager] removeItemAtPath:tempURL.path error:&error];
                if (error) {
                    NSLog(@"%@", error.localizedDescription);
                }
            }
            // Move file from app_id-Inbox to tmp/filename
            [[NSFileManager defaultManager] moveItemAtPath:url.path toPath:tempURL.path error:&error];
            if (error) {
                NSLog(@"%@", error.localizedDescription);
            } else {
                [newUrls addObject:tempURL];
            }
        }
		[self handleResult: newUrls];
		return;
    }
    
    [self handleResult: urls];
}


#pragma mark - UIImagePickerControllerDelegate
// ImagePicker delegate
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info {
    if (self.type == IMAGEPICKER) {
        NSURL *videoURL = [info objectForKey:UIImagePickerControllerMediaURL];
        [_imagePickerController dismissViewControllerAnimated:YES completion:nil];
        if (!self.result) {
          return;
        }
        if (videoURL != nil) {
          if (@available(iOS 13.0, *)) {
            NSString *fileName = [videoURL lastPathComponent];
            NSURL *destination =
                [NSURL fileURLWithPath:[NSTemporaryDirectory() stringByAppendingPathComponent:fileName]];

            if ([[NSFileManager defaultManager] isReadableFileAtPath:[videoURL path]]) {
              NSError *error;
              if (![[videoURL path] isEqualToString:[destination path]]) {
                [[NSFileManager defaultManager] copyItemAtURL:videoURL toURL:destination error:&error];

                if (error) {
                  self.result([FlutterError errorWithCode:@"flutter_image_picker_copy_video_error"
                                                  message:@"Could not cache the video file."
                                                  details:nil]);
                  self.result = nil;
                  return;
                }
              }
              videoURL = destination;
            }
          }
          self.result(videoURL.path);
          self.result = nil;
          _arguments = nil;
        } else {
          UIImage *image = [info objectForKey:UIImagePickerControllerEditedImage];
          if (image == nil) {
            image = [info objectForKey:UIImagePickerControllerOriginalImage];
          }
          NSNumber *maxWidth = [_arguments objectForKey:@"maxWidth"];
          NSNumber *maxHeight = [_arguments objectForKey:@"maxHeight"];
          NSNumber *imageQuality = [_arguments objectForKey:@"imageQuality"];
          NSNumber *desiredImageQuality = [self getDesiredImageQuality:imageQuality];

          PHAsset *originalAsset = [FLTImagePickerPhotoAssetUtil getAssetFromImagePickerInfo:info];

          if (maxWidth != (id)[NSNull null] || maxHeight != (id)[NSNull null]) {
            image = [FLTImagePickerImageUtil scaledImage:image
                                                maxWidth:maxWidth
                                               maxHeight:maxHeight
                                     isMetadataAvailable:YES];
          }

          if (!originalAsset) {
            // Image picked without an original asset (e.g. User took a photo directly)
            [self saveImageWithPickerInfo:info image:image imageQuality:desiredImageQuality];
          } else {
            [[PHImageManager defaultManager]
                requestImageDataForAsset:originalAsset
                                 options:nil
                           resultHandler:^(NSData *_Nullable imageData, NSString *_Nullable dataUTI,
                                           UIImageOrientation orientation, NSDictionary *_Nullable info) {
                             // maxWidth and maxHeight are used only for GIF images.
                             [self saveImageWithOriginalImageData:imageData
                                                            image:image
                                                         maxWidth:maxWidth
                                                        maxHeight:maxHeight
                                                     imageQuality:desiredImageQuality];
                           }];
          }
        }
    } else {
        
        if(_result == nil) {
            return;
        }
        
        NSURL *pickedVideoUrl = [info objectForKey:UIImagePickerControllerMediaURL];
        NSURL *pickedImageUrl;
        
        if(@available(iOS 13.0, *)) {
            
            if(pickedVideoUrl != nil) {
                NSString * fileName = [pickedVideoUrl lastPathComponent];
                NSURL * destination = [NSURL fileURLWithPath:[NSTemporaryDirectory() stringByAppendingPathComponent:fileName]];
                
                if([[NSFileManager defaultManager] isReadableFileAtPath: [pickedVideoUrl path]]) {
                    Log(@"Caching video file for iOS 13 or above...");
                    [[NSFileManager defaultManager] copyItemAtURL:pickedVideoUrl toURL:destination error:nil];
                    pickedVideoUrl = destination;
                }
            } else {
                pickedImageUrl = [info objectForKey:UIImagePickerControllerImageURL];
            }
            
        } else if (@available(iOS 11.0, *)) {
            pickedImageUrl = [info objectForKey:UIImagePickerControllerImageURL];
        } else {
            UIImage *pickedImage  = [info objectForKey:UIImagePickerControllerEditedImage];
            
            if(pickedImage == nil) {
                pickedImage = [info objectForKey:UIImagePickerControllerOriginalImage];
            }
            pickedImageUrl = [ImageUtils saveTmpImage:pickedImage];
        }
        
        [picker dismissViewControllerAnimated:YES completion:NULL];
        
        if(pickedImageUrl == nil && pickedVideoUrl == nil) {
            _result([FlutterError errorWithCode:@"file_picker_error"
                                        message:@"Temporary file could not be created"
                                        details:nil]);
            _result = nil;
            return;
        }
    }
    
    
    
}


#pragma mark - PHPickerViewControllerDelegate

#ifdef PHPicker

-(void)picker:(PHPickerViewController *)picker didFinishPicking:(NSArray<PHPickerResult *> *)results API_AVAILABLE(ios(14)){
    if (self.type == IMAGEPICKER) {
        [picker dismissViewControllerAnimated:YES completion:nil];
        if (results.count == 0) {
          if (self.result != nil) {
            self.result(nil);
            self.result = nil;
            self->_arguments = nil;
          }
          return;
        }
        dispatch_queue_t backgroundQueue =
            dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0);
        dispatch_async(backgroundQueue, ^{
          NSNumber *maxWidth = [self->_arguments objectForKey:@"maxWidth"];
          NSNumber *maxHeight = [self->_arguments objectForKey:@"maxHeight"];
          NSNumber *imageQuality = [self->_arguments objectForKey:@"imageQuality"];
          NSNumber *desiredImageQuality = [self getDesiredImageQuality:imageQuality];
          NSOperationQueue *operationQueue = [NSOperationQueue new];
          NSMutableArray *pathList = [self createNSMutableArrayWithSize:results.count];

          for (int i = 0; i < results.count; i++) {
            PHPickerResult *result = results[i];
            FLTPHPickerSaveImageToPathOperation *operation =
                [[FLTPHPickerSaveImageToPathOperation alloc] initWithResult:result
                                                                  maxHeight:maxHeight
                                                                   maxWidth:maxWidth
                                                        desiredImageQuality:desiredImageQuality
                                                             savedPathBlock:^(NSString *savedPath) {
                                                               pathList[i] = savedPath;
                                                             }];
            [operationQueue addOperation:operation];
          }
          [operationQueue waitUntilAllOperationsAreFinished];
          dispatch_async(dispatch_get_main_queue(), ^{
            [self handleSavedPathList:pathList];
          });
        });
    } else {
        if(_result == nil) {
            return;
        }
        
        if(self.group != nil) {
            return;
        }
        
        Log(@"Picker:%@ didFinishPicking:%@", picker, results);
        
        [picker dismissViewControllerAnimated:YES completion:nil];
        
        if(results.count == 0) {
            Log(@"FilePicker canceled");
            _result(nil);
            _result = nil;
            return;
        }
        
        NSMutableArray<NSURL *> * urls = [[NSMutableArray alloc] initWithCapacity:results.count];
        
        self.group = dispatch_group_create();
        
        if(self->_eventSink != nil) {
            self->_eventSink([NSNumber numberWithBool:YES]);
        }
        
        __block NSError * blockError;
        
        for (NSInteger index = 0; index < results.count; ++index) {//PHPickerResult *result in results
            [urls addObject:[NSURL URLWithString:@""]];
            dispatch_group_enter(_group);
			PHPickerResult * result = [results objectAtIndex: index];
            [result.itemProvider loadFileRepresentationForTypeIdentifier:@"public.item" completionHandler:^(NSURL * _Nullable url, NSError * _Nullable error) {
                
                if(url == nil) {
                    blockError = error;
                    Log("Could not load the picked given file: %@", blockError);
                    dispatch_group_leave(self->_group);
                    return;
                }
                
                long timestamp = (long)([[NSDate date] timeIntervalSince1970] * 1000);
				NSString * filenameWithoutExtension = [url.lastPathComponent stringByDeletingPathExtension];
				NSString * fileExtension = url.pathExtension;
                NSString * filename = [NSString stringWithFormat:@"%@-%ld.%@", filenameWithoutExtension, timestamp, fileExtension];
                NSString * extension = [filename pathExtension];
                NSFileManager * fileManager = [[NSFileManager alloc] init];
                NSURL * cachedUrl;
                
                // Check for live photos
                if(self.allowCompression && [extension isEqualToString:@"pvt"]) {
                    NSArray * files = [fileManager contentsOfDirectoryAtURL:url includingPropertiesForKeys:@[] options:NSDirectoryEnumerationSkipsHiddenFiles error:nil];
                    
                    for (NSURL * item in files) {
                        if (UTTypeConformsTo(UTTypeCreatePreferredIdentifierForTag(kUTTagClassFilenameExtension, CFBridgingRetain([item pathExtension]), NULL), kUTTypeImage)) {
                            
                            //UIImage * img = [UIImage imageWithContentsOfFile:item.path];
                            //NSString * fileName = [[item.path lastPathComponent] stringByDeletingPathExtension];
                            //NSData * data = UIImageJPEGRepresentation(img, 1);
                            //NSString * tmpFile = [NSTemporaryDirectory() stringByAppendingPathComponent:[fileName stringByAppendingString:@".jpeg"]];
                            NSData *assetData = [NSData dataWithContentsOfURL:item];
                            //Convert any type of image to jpeg
                            NSData *convertedImageData = UIImageJPEGRepresentation([UIImage imageWithData:assetData], 1.0);
                            //Get meta data from asset
                            NSDictionary *metaData = [ImageUtils getMetaDataFromImageData:assetData];
                            //Append meta data into jpeg of live photo
                            NSData *data = [ImageUtils imageFromImage:convertedImageData withMetaData:metaData];
                            //Save jpeg
                            NSString * filenameWithoutExtension = [filename stringByDeletingPathExtension];
                            NSString * tmpFile = [NSTemporaryDirectory() stringByAppendingPathComponent:[filenameWithoutExtension stringByAppendingString:@".jpeg"]];
                            cachedUrl = [NSURL fileURLWithPath: tmpFile];

                            if([fileManager fileExistsAtPath:tmpFile]) {
                                [fileManager removeItemAtPath:tmpFile error:nil];
                            }
                            
                            if([fileManager createFileAtPath:tmpFile contents:data attributes:nil]) {
                                filename = tmpFile;
                            } else {
                                Log("%@ Error while caching picked Live photo", self);
                            }
                            break;
                        }
                    }
                } else {
                    NSString * cachedFile = [NSTemporaryDirectory() stringByAppendingPathComponent:filename];
                    
                    if([fileManager fileExistsAtPath:cachedFile]) {
                        [fileManager removeItemAtPath:cachedFile error:NULL];
                    }
                    
                    cachedUrl = [NSURL fileURLWithPath: cachedFile];
                    
                    NSError *copyError;
                    [fileManager copyItemAtURL: url
                                         toURL: cachedUrl
                                         error: &copyError];
                    
                    if (copyError) {
                        Log("%@ Error while caching picked file: %@", self, copyError);
                        return;
                    }
                }
                
                
                [urls replaceObjectAtIndex:index withObject:cachedUrl];//[urls addObject:cachedUrl];
                dispatch_group_leave(self->_group);
            }];
        }
        
        dispatch_group_notify(_group, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0),^{
            self->_group = nil;
            if(self->_eventSink != nil) {
                self->_eventSink([NSNumber numberWithBool:NO]);
            }
            
            if(blockError) {
                self->_result([FlutterError errorWithCode:@"file_picker_error"
                                            message:@"Temporary file could not be created"
                                            details:blockError.description]);
                self->_result = nil;
                return;
            }
            [self handleResult:urls];
        });
    }
}

#endif


// AudioPicker delegate
- (void)mediaPicker: (MPMediaPickerController *)mediaPicker didPickMediaItems:(MPMediaItemCollection *)mediaItemCollection
{
    [mediaPicker dismissViewControllerAnimated:YES completion:NULL];
    int numberOfItems = (int)[mediaItemCollection items].count;
    
    if(numberOfItems == 0) {
        return;
    }
    
    if(_eventSink != nil) {
        _eventSink([NSNumber numberWithBool:YES]);
    }
    
    NSMutableArray<NSURL *> * urls = [[NSMutableArray alloc] initWithCapacity:numberOfItems];
    
    for(MPMediaItemCollection * item in [mediaItemCollection items]) {
        NSURL * cachedAsset = [FileUtils exportMusicAsset: [item valueForKey:MPMediaItemPropertyAssetURL] withName: [item valueForKey:MPMediaItemPropertyTitle]];
        [urls addObject: cachedAsset];
    }
    
    if(_eventSink != nil) {
        _eventSink([NSNumber numberWithBool:NO]);
    }
    
    if(urls.count == 0) {
        Log(@"Couldn't retrieve the audio file path, either is not locally downloaded or the file is DRM protected.");
    }
    [self handleResult:urls];
}

#pragma mark - Actions canceled
//
//- (void)presentationControllerDidDismiss:(UIPresentationController *)controller {
//    Log(@"FilePicker canceled");
//    if (self.result != nil) {
//        self.result(nil);
//        self.result = nil;
//    }
//}

- (void)mediaPickerDidCancel:(MPMediaPickerController *)controller {
    Log(@"FilePicker canceled");
    _result(nil);
    _result = nil;
    [controller dismissViewControllerAnimated:YES completion:NULL];
}

- (void)documentPickerWasCancelled:(UIDocumentPickerViewController *)controller {
    Log(@"FilePicker canceled");
    _result(nil);
    _result = nil;
    [controller dismissViewControllerAnimated:YES completion:NULL];
}

- (void)imagePickerControllerDidCancel:(UIImagePickerController *)picker {
    if (self.type == IMAGEPICKER) {
        [_imagePickerController dismissViewControllerAnimated:YES completion:nil];
        if (!self.result) {
          return;
        }
        self.result(nil);
        self.result = nil;
        _arguments = nil;
    } else {
        Log(@"FilePicker canceled");
        _result(nil);
        _result = nil;
        [picker dismissViewControllerAnimated:YES completion:NULL];
    }

}

#pragma mark - Alert dialog

- (void)showCamera {
  @synchronized(self) {
    if (_imagePickerController.beingPresented) {
      return;
    }
  }
  UIImagePickerControllerCameraDevice device = [self getCameraDeviceFromArguments:_arguments];
  // Camera is not available on simulators
  if ([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera] &&
      [UIImagePickerController isCameraDeviceAvailable:device]) {
    _imagePickerController.sourceType = UIImagePickerControllerSourceTypeCamera;
    _imagePickerController.cameraDevice = device;
    [[self viewControllerWithWindow:nil] presentViewController:_imagePickerController
                                                      animated:YES
                                                    completion:nil];
  } else {
    UIAlertController *cameraErrorAlert = [UIAlertController
        alertControllerWithTitle:NSLocalizedString(@"Error", @"Alert title when camera unavailable")
                         message:NSLocalizedString(@"Camera not available.",
                                                   "Alert message when camera unavailable")
                  preferredStyle:UIAlertControllerStyleAlert];
    [cameraErrorAlert
        addAction:[UIAlertAction actionWithTitle:NSLocalizedString(
                                                     @"OK", @"Alert button when camera unavailable")
                                           style:UIAlertActionStyleDefault
                                         handler:^(UIAlertAction *action){
                                         }]];
    [[self viewControllerWithWindow:nil] presentViewController:cameraErrorAlert
                                                      animated:YES
                                                    completion:nil];
    self.result(nil);
    self.result = nil;
    _arguments = nil;
  }
}

- (void)checkCameraAuthorization {
  AVAuthorizationStatus status = [AVCaptureDevice authorizationStatusForMediaType:AVMediaTypeVideo];

  switch (status) {
    case AVAuthorizationStatusAuthorized:
      [self showCamera];
      break;
    case AVAuthorizationStatusNotDetermined: {
      [AVCaptureDevice requestAccessForMediaType:AVMediaTypeVideo
                               completionHandler:^(BOOL granted) {
                                 dispatch_async(dispatch_get_main_queue(), ^{
                                   if (granted) {
                                     [self showCamera];
                                   } else {
                                     [self errorNoCameraAccess:AVAuthorizationStatusDenied];
                                   }
                                 });
                               }];
      break;
    }
    case AVAuthorizationStatusDenied:
    case AVAuthorizationStatusRestricted:
    default:
      [self errorNoCameraAccess:status];
      break;
  }
}

- (void)checkPhotoAuthorization {
  PHAuthorizationStatus status = [PHPhotoLibrary authorizationStatus];
  switch (status) {
    case PHAuthorizationStatusNotDetermined: {
      [PHPhotoLibrary requestAuthorization:^(PHAuthorizationStatus status) {
        dispatch_async(dispatch_get_main_queue(), ^{
          if (status == PHAuthorizationStatusAuthorized) {
            [self showPhotoLibrary:UIImagePickerClassType];
          } else {
            [self errorNoPhotoAccess:status];
          }
        });
      }];
      break;
    }
    case PHAuthorizationStatusAuthorized:
      [self showPhotoLibrary:UIImagePickerClassType];
      break;
    case PHAuthorizationStatusDenied:
    case PHAuthorizationStatusRestricted:
    default:
      [self errorNoPhotoAccess:status];
      break;
  }
}

- (void)checkPhotoAuthorizationForAccessLevel API_AVAILABLE(ios(14)) {
  PHAuthorizationStatus status = [PHPhotoLibrary authorizationStatus];
  switch (status) {
    case PHAuthorizationStatusNotDetermined: {
      [PHPhotoLibrary
          requestAuthorizationForAccessLevel:PHAccessLevelReadWrite
                                     handler:^(PHAuthorizationStatus status) {
                                       dispatch_async(dispatch_get_main_queue(), ^{
                                         if (status == PHAuthorizationStatusAuthorized) {
                                           [self showPhotoLibrary:PHPickerClassType];
                                         } else if (status == PHAuthorizationStatusLimited) {
                                           [self showPhotoLibrary:PHPickerClassType];
                                         } else {
                                           [self errorNoPhotoAccess:status];
                                         }
                                       });
                                     }];
      break;
    }
    case PHAuthorizationStatusAuthorized:
    case PHAuthorizationStatusLimited:
      [self showPhotoLibrary:PHPickerClassType];
      break;
    case PHAuthorizationStatusDenied:
    case PHAuthorizationStatusRestricted:
    default:
      [self errorNoPhotoAccess:status];
      break;
  }
}

- (void)errorNoCameraAccess:(AVAuthorizationStatus)status {
  switch (status) {
    case AVAuthorizationStatusRestricted:
      self.result([FlutterError errorWithCode:@"camera_access_restricted"
                                      message:@"The user is not allowed to use the camera."
                                      details:nil]);
      break;
    case AVAuthorizationStatusDenied:
    default:
      self.result([FlutterError errorWithCode:@"camera_access_denied"
                                      message:@"The user did not allow camera access."
                                      details:nil]);
      break;
  }
}

- (void)errorNoPhotoAccess:(PHAuthorizationStatus)status {
  switch (status) {
    case PHAuthorizationStatusRestricted:
      self.result([FlutterError errorWithCode:@"photo_access_restricted"
                                      message:@"The user is not allowed to use the photo."
                                      details:nil]);
      break;
    case PHAuthorizationStatusDenied:
    default:
      self.result([FlutterError errorWithCode:@"photo_access_denied"
                                      message:@"The user did not allow photo access."
                                      details:nil]);
      break;
  }
}

- (void)showPhotoLibrary:(ImagePickerClassType)imagePickerClassType {
  // No need to check if SourceType is available. It always is.
  switch (imagePickerClassType) {
    case PHPickerClassType:
      [[self viewControllerWithWindow:nil] presentViewController:_pickerViewController
                                                        animated:YES
                                                      completion:nil];
      break;
    case UIImagePickerClassType:
      _imagePickerController.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
      [[self viewControllerWithWindow:nil] presentViewController:_imagePickerController
                                                        animated:YES
                                                      completion:nil];
      break;
  }
}

- (NSNumber *)getDesiredImageQuality:(NSNumber *)imageQuality {
  if (![imageQuality isKindOfClass:[NSNumber class]]) {
    imageQuality = @1;
  } else if (imageQuality.intValue < 0 || imageQuality.intValue > 100) {
    imageQuality = @1;
  } else {
    imageQuality = @([imageQuality floatValue] / 100);
  }
  return imageQuality;
}

- (void)presentationControllerDidDismiss:(UIPresentationController *)presentationController {
  if (self.result != nil) {
    self.result(nil);
    self.result = nil;
    self->_arguments = nil;
  }
}

/**
 * Creates an NSMutableArray of a certain size filled with NSNull objects.
 *
 * The difference with initWithCapacity is that initWithCapacity still gives an empty array making
 * it impossible to add objects on an index larger than the size.
 *
 * @param size The length of the required array
 * @return NSMutableArray An array of a specified size
 */
- (NSMutableArray *)createNSMutableArrayWithSize:(NSUInteger)size {
  NSMutableArray *mutableArray = [[NSMutableArray alloc] initWithCapacity:size];
  for (int i = 0; i < size; [mutableArray addObject:[NSNull null]], i++)
    ;
  return mutableArray;
}



//- (void)imagePickerControllerDidCancel:(UIImagePickerController *)picker {
//  [_imagePickerController dismissViewControllerAnimated:YES completion:nil];
//  if (!self.result) {
//    return;
//  }
//  self.result(nil);
//  self.result = nil;
//  _arguments = nil;
//}

- (void)saveImageWithOriginalImageData:(NSData *)originalImageData
                                 image:(UIImage *)image
                              maxWidth:(NSNumber *)maxWidth
                             maxHeight:(NSNumber *)maxHeight
                          imageQuality:(NSNumber *)imageQuality {
  NSString *savedPath =
      [FLTImagePickerPhotoAssetUtil saveImageWithOriginalImageData:originalImageData
                                                             image:image
                                                          maxWidth:maxWidth
                                                         maxHeight:maxHeight
                                                      imageQuality:imageQuality];
  [self handleSavedPathList:@[ savedPath ]];
}

- (void)saveImageWithPickerInfo:(NSDictionary *)info
                          image:(UIImage *)image
                   imageQuality:(NSNumber *)imageQuality {
  NSString *savedPath = [FLTImagePickerPhotoAssetUtil saveImageWithPickerInfo:info
                                                                        image:image
                                                                 imageQuality:imageQuality];
  [self handleSavedPathList:@[ savedPath ]];
}

/**
 * Applies NSMutableArray on the FLutterResult.
 *
 * NSString must be returned by FlutterResult if the single image
 * mode is active. It is checked by maxImagesAllowed and
 * returns the first object of the pathlist.
 *
 * NSMutableArray must be returned by FlutterResult if the multi-image
 * mode is active. After the pathlist count is checked then it returns
 * the pathlist.
 *
 * @param pathList that should be applied to FlutterResult.
 */
- (void)handleSavedPathList:(NSArray <NSString*>*)pathList {
  if (!self.result) {
    return;
  }

  if (pathList) {
    if (![pathList containsObject:[NSNull null]]) {
      if ((self.maxImagesAllowed == 1)) {
        self.result(pathList.firstObject);
      } else {
        self.result(pathList);
      }
    } else {
      self.result([FlutterError errorWithCode:@"create_error"
                                      message:@"pathList's items should not be null"
                                      details:nil]);
    }
  } else {
    // This should never happen.
    self.result([FlutterError errorWithCode:@"create_error"
                                    message:@"pathList should not be nil"
                                    details:nil]);
  }
  self.result = nil;
  _arguments = nil;
}


#pragma mark - UIAdaptivePresentationControllerDelegate 全屏显示
- (UIModalPresentationStyle)adaptivePresentationStyleForPresentationController:(UIPresentationController *)controller traitCollection:(UITraitCollection *)traitCollection{
    return UIModalPresentationFullScreen;
}


@end
